﻿namespace Paw.Phone.Pages
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.Shell;
    using Microsoft.Phone.Tasks;
    using Paw.Phone.PivotContent;
    using Paw.Phone.ViewModel;
    using System.ComponentModel;
    using System.Threading;

    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Controls.Primitives;


    public partial class MainPage : PhoneApplicationPage
    {
        private Popup popup;
        private BackgroundWorker backroungWorker;
        private readonly ICloudClientFactory cloudClientFactory;

        public MainPage()
            : this(App.CloudClientFactory)
        {
        }

        public MainPage(ICloudClientFactory cloudClientFactory)
        {
            this.InitializeComponent();
            this.ShowPopup();

            this.cloudClientFactory = cloudClientFactory;

            this.PageTransitionReset.Begin();
            this.Loaded += (sender, args) =>
            {
                var userAlreadyLoggedIn = GetApplicationState<bool>("UserLoggedIn");

                if (userAlreadyLoggedIn)
                {
                    this.StartTransition();
                }
                else
                {
                    // If there is a valid authentication token available in the isolated storage,
                    // then the application navigates to the main pivot page and is registered with 
                    // the push notification service in case 'push notification' is enabled by the user.
                    // If there is not any valid authentication token available in the isolated storage,
                    // then the application navigates to the login page.
                    this.cloudClientFactory.VerifyLoggedIn(
                        () => this.StartTransition(),
                        () => this.NavigationService.Navigate(new Uri("/Pages/LoginPage.xaml", UriKind.Relative)));
                }
            };

            this.MainPivot.SelectionChanged += this.OnMainPivotSelectionChanged;
        }

        private void ShowPopup()
        {
            this.popup = new Popup();
            this.popup.Child = new PopupSplash();
            this.popup.IsOpen = true;
            StartLoadingData();
        }

        private void StartLoadingData()
        {
            backroungWorker = new BackgroundWorker();
            backroungWorker.DoWork += new DoWorkEventHandler(backroungWorker_DoWork);
            backroungWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backroungWorker_RunWorkerCompleted);
            backroungWorker.RunWorkerAsync();
        }

        void backroungWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Dispatcher.BeginInvoke(() =>
            {
                this.popup.IsOpen = false;

            }
            );
        }

        void backroungWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // Do some data loading on a background
            // We'll just sleep for the demo
            Thread.Sleep(7000);
        }

        public MainPageViewModel ViewModel
        {
            get { return this.DataContext as MainPageViewModel; }
            set { this.DataContext = value; }
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            this.PageTransitionReset.Begin();
        }

        private static T GetApplicationState<T>(string key)
        {
            if (!PhoneApplicationService.Current.State.ContainsKey(key))
            {
                return default(T);
            }

            return (T)PhoneApplicationService.Current.State[key];
        }

        private static void RemoveApplicationState(string key)
        {
            if (PhoneApplicationService.Current.State.ContainsKey(key))
            {
                PhoneApplicationService.Current.State.Remove(key);
            }
        }

        private static void SetApplicationState(string key, object value)
        {
            if (PhoneApplicationService.Current.State.ContainsKey(key))
            {
                PhoneApplicationService.Current.State.Remove(key);
            }

            PhoneApplicationService.Current.State.Add(key, value);
        }

        private void StartTransition()
        {
            this.PageTransitionIn.Begin();

            if (this.DataContext == null)
            {
                this.DataContext = new MainPageViewModel();
                this.LoadPivotItems();
            }
        }

        private void LoadPivotItems()
        {
            this.MainPivot.Items.Clear();

            var notificationsPage = new NotificationsPage();
            var notificationsPivot = new PivotItem();
            notificationsPivot.Header = "notifications";
            notificationsPivot.Name = "PushNotifications";
            notificationsPivot.Content = notificationsPage;
            notificationsPage.ViewModel = this.ViewModel.NotificationsViewModel;
            notificationsPage.BeginPushConnection += this.OnBeginPushConnection;
            notificationsPage.EndPushConnection += this.OnEndPushConnection;
            this.MainPivot.Items.Add(notificationsPivot);

            var tablesPage = new TablesPage();
            var tablesPivot = new PivotItem();
            tablesPivot.Header = "tables list";
            tablesPivot.Name = "TablesList";
            tablesPivot.Content = tablesPage;
            tablesPage.ViewModel = this.ViewModel.TablesPageViewModel;
            this.MainPivot.Items.Add(tablesPivot);

            var sampleDataTablesPage = new SampleDataTablePage();
            var sampleDataTablesPivot = new PivotItem();
            sampleDataTablesPivot.Header = "sample data";
            sampleDataTablesPivot.Name = "SampleDataRows";
            sampleDataTablesPivot.Content = sampleDataTablesPage;
            sampleDataTablesPage.ViewModel = this.ViewModel.SampleDataTablePageViewModel;
            sampleDataTablesPage.Navigate += this.OnNavigatePage;
            this.MainPivot.Items.Add(sampleDataTablesPivot);

            var listBlobsPage = new ListBlobsPage();
            var listBlobsPivot = new PivotItem();
            listBlobsPivot.Header = "list blobs";
            listBlobsPivot.Name = "ListBlobs";
            listBlobsPivot.Content = listBlobsPage;
            listBlobsPage.ViewModel = this.ViewModel.ListBlobsPageViewModel;
            listBlobsPage.TakePhoto += this.OnLaunchCamera;
            this.MainPivot.Items.Add(listBlobsPivot);

            var listQueuesPage = new ListQueuesPage();
            var listQueuesPivot = new PivotItem();
            listQueuesPivot.Header = "queues";
            listQueuesPivot.Name = "ListQueuesPage";
            listQueuesPivot.Content = listQueuesPage;
            listQueuesPage.ViewModel = this.ViewModel.ListQueuesPageViewModel;
            listQueuesPage.Navigate += this.OnNavigatePage;
            this.MainPivot.Items.Add(listQueuesPivot);

            this.MainPivot.SelectedItem = notificationsPivot;
        }

        private IEnumerable<IApplicationBarMenuItem> GetApplicationBarItemsByText(string text)
        {
            return this.ApplicationBar.MenuItems.Cast<IApplicationBarMenuItem>()
                        .Where(m => m.Text.Equals(text, StringComparison.OrdinalIgnoreCase))
                        .Concat(
                            this.ApplicationBar.Buttons.Cast<IApplicationBarMenuItem>()
                                .Where(b => b.Text.Equals(text, StringComparison.OrdinalIgnoreCase)));
        }

        private void OnMainPivotSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var currentItem = this.MainPivot.SelectedItem as PivotItem;
            if (currentItem != null)
            {
                var currentView = currentItem.Content as UserControl;
                if (currentView != null)
                {
                    var viewModel = currentView.DataContext as PivotItemViewModel;
                    if (viewModel != null)
                    {
                        viewModel.UpdateApplicationBarButtons(this.ApplicationBar, new[] { "logout" });
                    }
                }
            }
        }

        private void OnLaunchCamera(object sender, EventArgs e)
        {
            var cameraCaptureTask = new CameraCaptureTask();
            cameraCaptureTask.Completed += this.OnCameraCaptureTaskCompleted;
            cameraCaptureTask.Show();
        }

        private void OnCameraCaptureTaskCompleted(object sender, PhotoResult e)
        {
            if (e.TaskResult == TaskResult.OK)
            {
                SetApplicationState("PhotoResult", e);

                // Delay navigation until the first navigated event.
                this.NavigationService.Navigated += this.OnNavigatedCompleted;
            }
        }

        private void OnNavigatedCompleted(object sender, EventArgs e)
        {
            // Do the delayed navigation from the main page.
            this.NavigationService.Navigate(new Uri("/Pages/UploadPhotoPage.xaml", UriKind.Relative));
            this.NavigationService.Navigated -= this.OnNavigatedCompleted;
        }

        private void OnNavigatePage(object sender, NavigationEventArgs e)
        {
            this.NavigationService.Navigate(e.Uri);
        }

        private void OnLogout(object sender, EventArgs e)
        {
            RemoveApplicationState("UserLoggedIn");

            this.MainPivot.IsEnabled = false;
            this.MainPivot.Opacity = 0.3d;
            this.LogOutStackPanel.Opacity = 1;
            foreach (var button in this.GetApplicationBarItemsByText("logout"))
            {
                button.IsEnabled = false;
            }

            var pushNotificationClient = App.CloudClientFactory.ResolvePushNotificationClient();
            pushNotificationClient.Disconnect(
                r =>
                {
                    this.Dispatcher.BeginInvoke(
                        () =>
                        {
                            this.MainPivot.IsEnabled = true;
                            this.MainPivot.Opacity = 1;
                            this.LogOutStackPanel.Opacity = 0;

                            foreach (var button in GetApplicationBarItemsByText("logout"))
                            {
                                button.IsEnabled = true;
                            }

                            if (r.Exception != null)
                            {
                                MessageBox.Show(r.Exception.Message, "Push Unregistration Error", MessageBoxButton.OK);
                            }

                            // Clean the current authentication token and view models.
                            App.CloudClientFactory.CleanAuthenticationToken();
                            this.DataContext = null;
                            this.MainPivot.Items.Clear();

                            // Navigate to the login page.
                            this.NavigationService.Navigate(new Uri("/Pages/LoginPage.xaml", UriKind.Relative));
                        });
                });
        }

        private void OnBeginPushConnection(object sender, EventArgs e)
        {
            var items = this.GetApplicationBarItemsByText("logout");
            foreach (var item in items)
            {
                item.IsEnabled = false;
            }
        }

        private void OnEndPushConnection(object sender, EventArgs e)
        {
            var items = this.GetApplicationBarItemsByText("logout");
            foreach (var item in items)
            {
                item.IsEnabled = true;
            }
        }
    }
}